/**
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * $Id: RubroTiempoEstimado.java, 2009/11/06 15:42:22
 * Bisa Corporation (Bogotá - Colombia)
 * Departamento de Ingeniería de Sistemas
 *
 * Proyecto ITM
 * Autor: Jimmy Ramírez Duque
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */
package investigaciones_itm.Presupuestos;

import com.sun.rave.web.ui.appbase.AbstractPageBean;
import java.util.logging.Level;
import java.util.logging.Logger;
import itm.bo.presupuestos.PresupuestosBO;
import itm.vo.presupuestos.periodoRubroVO;
import itm.vo.presupuestos.rubroProyectoVO;
import java.util.ArrayList;
import java.util.List;
import javax.faces.component.UIParameter;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;
import javax.servlet.http.HttpSession;
import javax.faces.FacesException;

/**
 * Gestiona el presupuesto estimado por tiempo
 * @author jimmy
 */
public class RubroTiempoEstimado extends AbstractPageBean {

    /*---------------------------------------------OBJETOS*/
    private EstimacionPresupuestal estimacionPresupuestal;
    private PresupuestosBO presupuestosBO;
    private periodoRubroVO periodoRubro;
    /*--------------------------------------------LISTADOS*/
    private List<rubroProyectoVO> listaRubroProy = new ArrayList<rubroProyectoVO>();
    private List<periodoRubroVO> listaPeriodo = new ArrayList<periodoRubroVO>();
    /*---------------------------------------------VARIABLES*/
    private long idProyecto;
    private int duraProyecto;
    private String tipoTiempo;
    private long valorPeriodo;
    private double totalPresup;
    private long presupDistribuido;
    private HttpSession session;
    /*-------------------------------------------Variables que controlan la visibilidad de los componentes*/
    private boolean boolBotonSiguiente;
    private boolean boolBotonGuardar;
    private boolean boolInputText;
    /*----------------------------------------CONSTANTES*/
    private String PRESUP_STATUS_TIEMPO = "E_TIM";

    /**
     * CONSTRUCTOR
     */
    public RubroTiempoEstimado() {
        this.inicializar();
    }

    /**
     * Inicializa los valores del formulario
     */
    protected void inicializar() {
        this.inicializarObjetos();
        this.cargarVariablesSesion();
        this.cargarRubros();
        this.setBoolBotonSiguiente(true);
        this.cargarValriablesSesionLocal();
    }

    /**
     * Inicializa los objetos de la clase
     */
    protected void inicializarObjetos() {
        estimacionPresupuestal = new EstimacionPresupuestal();
        presupuestosBO = new PresupuestosBO();
    }

    /**
     * Carga los atributos guardados en sesion
     */
    protected void cargarVariablesSesion() {
        if (estimacionPresupuestal.getSesion().getAttribute("idProyecto") != null) {
            this.setIdProyecto((Long) estimacionPresupuestal.getSesion().getAttribute("idProyecto"));

        }
        if (estimacionPresupuestal.getSesion().getAttribute("totalPresup") != null) {
            this.setTotalPresup((Double) estimacionPresupuestal.getSesion().getAttribute("totalPresup"));
        }
        if (estimacionPresupuestal.getSesion().getAttribute("lista.Rubro.Proy") != null) {
            this.setListaRubroProy((List<rubroProyectoVO>) estimacionPresupuestal.getSesion().getAttribute("lista.Rubro.Proy"));
        }


    }

    /**
     * Carga los atributos locales guardados en sesion
     */
    protected void cargarValriablesSesionLocal() {
        if (this.getSession().getAttribute("listRubro") != null) {
            this.setListaRubroProy((List<rubroProyectoVO>) this.getSession().getAttribute("listRubro"));
        }
        if (this.getSession().getAttribute("boolBotonGuardar") != null) {
            this.setBoolBotonGuardar((Boolean) this.getSession().getAttribute("boolBotonGuardar"));
        }
        if (this.getSession().getAttribute("boolBotonSiguiente") != null) {
            this.setBoolBotonSiguiente((Boolean) this.getSession().getAttribute("boolBotonSiguiente"));
        }
        if (this.getSession().getAttribute("boolInputText") != null) {
            this.setBoolInputText((Boolean) this.getSession().getAttribute("boolInputText"));
        }
        if (this.getSession().getAttribute("totalPresup") != null) {
            this.setTotalPresup((Double) this.getSession().getAttribute("totalPresup"));
        }
        if (this.getSession().getAttribute("presupDistribuido") != null) {
            this.setPresupDistribuido((Long) this.getSession().getAttribute("presupDistribuido"));
        }
    }

    /**
     * Cargar la lista de rubros por proyecto
     */
    protected void cargarRubros() {
        try {
            // this.setListaRubroProy(presupuestosBO.listaRubroProyecto(idProyecto));
            this.setDuraProyecto(presupuestosBO.tempoEstProy(idProyecto));
            this.setTipoTiempo(presupuestosBO.tipo_Tiempo_Est(idProyecto));
            this.cargarPeriodos();
        } catch (Exception ex) {
            Logger.getLogger(RubroTiempoEstimado.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Carga los periodos establecidos por rubro
     */
    protected void cargarPeriodos() {
        if (estimacionPresupuestal.getSesion().getAttribute("status") != null) {
            this.setListaRubroProy((List<rubroProyectoVO>) estimacionPresupuestal.getSesion().getAttribute("lista.Rubro.Proy"));
            this.calcularPresupuestoExistente();
            this.setBoolBotonGuardar(true);
            this.setBoolBotonSiguiente(false);
            this.setBoolInputText(true);
            this.getSession().setAttribute("boolInpText", this.isBoolInputText());
            this.getSession().setAttribute("boolBotGuardar", this.isBoolBotonGuardar());
            this.getSession().setAttribute("boolBotonSiguiente", this.isBoolBotonSiguiente());
        } else {
            for (int j = 0; j < this.getListaRubroProy().size(); j++) {
                if (this.getListaRubroProy().get(j).getListaPeriodos().size() == 0) {
                    for (int i = 1; i <= this.getDuraProyecto(); i++) {
                        periodoRubro = new periodoRubroVO();
                        periodoRubro.setPeriodo(i);
                        periodoRubro.setValorPeriodo(this.getValorPeriodo());

                        this.getListaRubroProy().get(j).getListaPeriodos().add(periodoRubro);
                    }
                }
            }
        }
    }

    public void calcularPresupuestoExistente() {
        double totalPeriodo = 0;
        double totalFuente = 0;
        double totalPresupuesto = 0;
        double presuDistribuido = 0;
        for (int i = 0; i < this.getListaRubroProy().size(); i++) {
            for (int j = 0; j < this.getListaRubroProy().get(i).getListaPeriodos().size(); j++) {
                totalPeriodo = totalPeriodo + this.getListaRubroProy().get(i).getListaPeriodos().get(j).getValorPeriodo();
            }
            for (int k = 0; k < this.getListaRubroProy().get(i).getListaRubros().size(); k++) {
                totalFuente = totalFuente + this.getListaRubroProy().get(i).getListaRubros().get(k).getValorFuenteF();
            }
            this.getListaRubroProy().get(i).setTotal(totalPeriodo);
            totalPresupuesto = totalPresupuesto + totalFuente;
            totalFuente = 0;
            totalPeriodo = 0;
        }
        for (int i = 0; i < this.getListaRubroProy().size(); i++) {
            presuDistribuido = (long) (presuDistribuido + this.getListaRubroProy().get(i).getTotal());
        }
        this.setTotalPresup(totalPresupuesto);
        this.setPresupDistribuido((long) presuDistribuido);
        this.getSession().setAttribute("presupDistribuido", this.getPresupDistribuido());
        this.getSession().setAttribute("totalPresup", this.getTotalPresup());
    }

    /**
     * Asigna los valores a cada periodo
     * calcula el valor total por rubro
     * valida que el presupuesto distribuido no sobrepase el presupuesto disponible
     * @param vce
     */
    public void actionValorPeriodo(ValueChangeEvent vce) {
        String valorAnteriorPeriodo = vce.getOldValue().toString();
        String valorNuevoPeriodo = vce.getNewValue().toString();
        double totalPeriodo = 0;
        double totalFuente = 0;
        long totalPresupuesto = 0;
        UIParameter periodoParam = (UIParameter) vce.getComponent().findComponent("periodo");
        UIParameter idRubroParam = (UIParameter) vce.getComponent().findComponent("idRubro");
        for (int i = 0; i < this.getListaRubroProy().size(); i++) {
            if (this.getListaRubroProy().get(i).getIdRubro() == Integer.parseInt(idRubroParam.getValue().toString())) {
                for (int j = 0; j < this.getListaRubroProy().get(i).getListaPeriodos().size(); j++) {
                    if (this.getListaRubroProy().get(i).getListaPeriodos().get(j).getPeriodo() == Integer.parseInt(periodoParam.getValue().toString())) {
                        this.getListaRubroProy().get(i).getListaPeriodos().get(j).setValorPeriodo(Double.parseDouble(valorNuevoPeriodo));
                    }
                }
            }
        }
        for (int i = 0; i < this.getListaRubroProy().size(); i++) {
            for (int j = 0; j < this.getListaRubroProy().get(i).getListaPeriodos().size(); j++) {
                totalPeriodo = totalPeriodo + this.getListaRubroProy().get(i).getListaPeriodos().get(j).getValorPeriodo();
            }
            for (int k = 0; k < this.getListaRubroProy().get(i).getListaRubros().size(); k++) {
                totalFuente = totalFuente + this.getListaRubroProy().get(i).getListaRubros().get(k).getValorFuenteF();
            }
            this.getListaRubroProy().get(i).setTotal(totalPeriodo);
            this.getListaRubroProy().get(i).setTotalRubro(totalFuente);
            if (this.getListaRubroProy().get(i).getTotal() > this.getListaRubroProy().get(i).getTotalRubro()) {
                error("El presupuesto a distribuir no puede sobrepasar el presupuesto disponible " + this.getListaRubroProy().get(i).getTotalRubro() + " para el rubro " + this.getListaRubroProy().get(i).getNombreRubro());
                totalPeriodo = 0;
                this.recargarListaRubroProy(idRubroParam, periodoParam, valorAnteriorPeriodo, totalPresupuesto, totalPeriodo);
            }
            totalPeriodo = 0;
            totalFuente = 0;
        }

        for (int i = 0; i < this.getListaRubroProy().size(); i++) {
            totalPresupuesto = (long) (totalPresupuesto + this.getListaRubroProy().get(i).getTotal());
        }
        this.setPresupDistribuido(totalPresupuesto);
        if (totalPresupuesto > this.getTotalPresup()) {
            this.recargarListaRubroProy(idRubroParam, periodoParam, valorAnteriorPeriodo, totalPresupuesto, totalPeriodo);
        }
        this.getSession().setAttribute("listaRubro", this.getListaRubroProy());
        this.getSession().setAttribute("presupDistribuido", this.getPresupDistribuido());
    }

    /**
     * Recargar la lista de rubros por proyecto,
     * si el presupuesto distribuido soprepasa el presupuesto disponible del proyecto
     * @param idRubroParam
     * @param periodoParam
     * @param valorAnteriorPeriodo
     * @param totalPresupuesto
     * @param totalPeriodo
     */
    protected void recargarListaRubroProy(UIParameter idRubroParam, UIParameter periodoParam, String valorAnteriorPeriodo, long totalPresupuesto, double totalPeriodo) {

        totalPresupuesto = 0;
        for (int i = 0; i < this.getListaRubroProy().size(); i++) {
            if (this.getListaRubroProy().get(i).getIdRubro() == Integer.parseInt(idRubroParam.getValue().toString())) {
                for (int j = 0; j < this.getListaRubroProy().get(i).getListaPeriodos().size(); j++) {
                    if (this.getListaRubroProy().get(i).getListaPeriodos().get(j).getPeriodo() == Integer.parseInt(periodoParam.getValue().toString())) {
                        this.getListaRubroProy().get(i).getListaPeriodos().get(j).setValorPeriodo(Double.parseDouble(valorAnteriorPeriodo));
                    }
                }
            }
        }
        for (int i = 0; i < this.getListaRubroProy().size(); i++) {
            for (int j = 0; j < this.getListaRubroProy().get(i).getListaPeriodos().size(); j++) {
                totalPeriodo = totalPeriodo + this.getListaRubroProy().get(i).getListaPeriodos().get(j).getValorPeriodo();
            }
            this.getListaRubroProy().get(i).setTotal(totalPeriodo);
            totalPeriodo = 0;
        }
        for (int i = 0; i < this.getListaRubroProy().size(); i++) {
            totalPresupuesto = (long) (totalPresupuesto + this.getListaRubroProy().get(i).getTotal());
        }
        this.setPresupDistribuido(totalPresupuesto);
    }

    /**
     * Guarda en base de datos los valores asignados a los periodos por rubro
     */
    public void actionBotonGuardar() {
        try {
            if(presupDistribuido>0){
            presupuestosBO.registrarPresupPeriodoEst(idProyecto, PRESUP_STATUS_TIEMPO, listaRubroProy);
            this.setBoolBotonGuardar(true);
            this.setBoolBotonSiguiente(false);
            this.setBoolInputText(true);
            this.getSession().setAttribute("boolInpText", this.isBoolInputText());
            this.getSession().setAttribute("boolBotGuardar", this.isBoolBotonGuardar());
            this.getSession().setAttribute("boolBotonSiguiente", this.isBoolBotonSiguiente());
            info("Se registro correctamente el Presupuesto Estimado por Periodo");
            }else{
            error("El presupuesto distribuido no puede ser igual a cero");
            }
        } catch (Exception ex) {
            Logger.getLogger(RubroTiempoEstimado.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /*------------------------------GETTERS y SETTERS*/
    public List<rubroProyectoVO> getListaRubroProy() {
        return listaRubroProy;
    }

    public void setListaRubroProy(List<rubroProyectoVO> listaRubroProy) {
        this.listaRubroProy = listaRubroProy;
    }

    public long getIdProyecto() {
        return idProyecto;
    }

    public void setIdProyecto(long idProyecto) {
        this.idProyecto = idProyecto;
    }

    public int getDuraProyecto() {
        return duraProyecto;
    }

    public void setDuraProyecto(int duraProyecto) {
        this.duraProyecto = duraProyecto;
    }

    public List<periodoRubroVO> getListaPeriodo() {
        return listaPeriodo;
    }

    public void setListaPeriodo(List<periodoRubroVO> listaPeriodo) {
        this.listaPeriodo = listaPeriodo;
    }

    public String getTipoTiempo() {
        return tipoTiempo;
    }

    public void setTipoTiempo(String tipoTiempo) {
        this.tipoTiempo = tipoTiempo;
    }

    public long getValorPeriodo() {
        return valorPeriodo;
    }

    public void setValorPeriodo(long valorPeriodo) {
        this.valorPeriodo = valorPeriodo;
    }

    public double getTotalPresup() {
        return totalPresup;
    }

    public void setTotalPresup(double totalPresup) {
        this.totalPresup = totalPresup;
    }

    public HttpSession getSession() {
        return (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);
    }

    public void setSession(HttpSession session) {
        this.session = session;
    }

    public long getPresupDistribuido() {
        return presupDistribuido;
    }

    public void setPresupDistribuido(long presupDistribuido) {
        this.presupDistribuido = presupDistribuido;
    }

    public boolean isBoolBotonGuardar() {
        return boolBotonGuardar;
    }

    public void setBoolBotonGuardar(boolean boolBotonGuardar) {
        this.boolBotonGuardar = boolBotonGuardar;
    }

    public boolean isBoolBotonSiguiente() {
        return boolBotonSiguiente;
    }

    public void setBoolBotonSiguiente(boolean boolBotonSiguiente) {
        this.boolBotonSiguiente = boolBotonSiguiente;
    }

    public boolean isBoolInputText() {
        return boolInputText;
    }

    public void setBoolInputText(boolean boolInputText) {
        this.boolInputText = boolInputText;
    }

    /**
     * <p>Callback method that is called whenever a page is navigated to,
     * either directly via a URL, or indirectly via page navigation.
     * Customize this method to acquire resources that will be needed
     * for event handlers and lifecycle methods, whether or not this
     * page is performing post back processing.</p>
     *
     * <p>Note that, if the current request is a postback, the property
     * values of the components do <strong>not</strong> represent any
     * values submitted with this request.  Instead, they represent the
     * property values that were saved for this view when it was rendered.</p>
     */
    @Override
    public void init() {

        // Perform initializations inherited from our superclass
        super.init();
// Perform application initialization that must complete
        // *before* managed components are initialized
        // TODO - add your own initialiation code here
// <editor-fold defaultstate="collapsed" desc="Visual-Web-managed Component Initialization">
// Initialize automatically managed components
        // *Note* - this logic should NOT be modified
        try {
            _init();
        } catch (Exception e) {
            log("Page1 Initialization Failure", e);
            throw e instanceof FacesException ? (FacesException) e : new FacesException(e);
        }
    }

    /**
     * <p>Callback method that is called after the component tree has been
     * restored, but before any event processing takes place.  This method
     * will <strong>only</strong> be called on a postback request that
     * is processing a form submit.  Customize this method to allocate
     * resources that will be required in your event handlers.</p>
     */
    @Override
    public void preprocess() {
    }

    /**
     * <p>Callback method that is called just before rendering takes place.
     * This method will <strong>only</strong> be called for the page that
     * will actually be rendered (and not, for example, on a page that
     * handled a postback and then navigated to a different page).  Customize
     * this method to allocate resources that will be required for rendering
     * this page.</p>
     */
    @Override
    public void prerender() {
    }

    /**
     * <p>Callback method that is called after rendering is completed for
     * this request, if <code>init()</code> was called (regardless of whether
     * or not this was the page that was actually rendered).  Customize this
     * method to release resources acquired in the <code>init()</code>,
     * <code>preprocess()</code>, or <code>prerender()</code> methods (or
     * acquired during execution of an event handler).</p>
     */
    @Override
    public void destroy() {
    }

    /**
     * <p>Automatically managed component initialization.  <strong>WARNING:</strong>
     * This method is automatically generated, so any user-specified code inserted
     * here is subject to being replaced.</p>
     */
    private void _init() {
    }
}